/*
 * Formula Parser
 * @Version: revised version for ABSL
 * @Revised by Hao Ji
 */

package parser;

import java.io.*;
import java.text.MessageFormat;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.*;
import java.util.*;



public class Parser {
	protected static final String SIMULATION_MODEL = "mainmodel";
	protected static final String SIMULATION_UNIT_NAME = "name";
	protected static final String SIMULATION_UNIT_NATURE = "nature";
	protected static final String SIMULATION_UNIT_NATURE_AUX = "aux";
	protected static final String SIMULATION_UNIT_NATURE_LEVEL = "level";
	protected static final String SIMULATION_UNIT_NATURE_CONST = "const";
	protected static final String SIMULATION_UNIT_NATURE_UNIT = "unit";

	protected static final String SIMULATION_UNIT_TYPE = "type";
	protected static final String SIMULATION_UNIT_DIM = "dim";
	protected static final String SIMULATION_UNIT_UNIT = "unit";

	protected static final String SIMULATION_UNIT_INIT = "init";
	protected static final String SIMULATION_UNIT_DEF = "def";

	protected static final String SIMULATION_UNIT_LEVEL_RESERVOIR = "reservoir";
	protected static final String SIMULATION_UNIT_LEVEL_IN = "inflow";
	protected static final String SIMULATION_UNIT_LEVEL_OUT = "outflow";

	protected static final String SIMULATION_UNIT_INTEGRATION = "integration";
	protected static final String SIMULATION_UNIT_INTEGRATION_FIRSTORDER = "firstorder";
	protected static final String SIMULATION_UNIT_INTEGRATION_ZEROORDER = "zeroorder";
	protected static final String SIMULATION_UNIT_IMMEDIATE = "immediate";
	protected static final String SIMULATION_UNIT_PERMANENT = "permanent";

	protected static final String SIMULATION_UNIT_DOC = "doc";
	protected static final String SIMULATION_UNIT_NOTE = "note";
        protected String output = new String();

	/** findet Zeilen, die nur Seitennummer und/oder Sonderzeichen enthalten */
	protected static final Pattern trim_ignore = Pattern
			.compile("^\\s*[\\d=\\x0C]+\\s*$");

	/** findet Leerzeichen am Anfang einer Zeile */
	protected static final Pattern trim_begin = Pattern.compile("^\\s+");

	/**
	 * findet feste Leerzeichen und/oder doppelte Leerzeichen und Kommentare
	 * innerhalb einer Zeile
	 */
	protected static final Pattern trim_inner = Pattern
			.compile("\\s*\\x1F\\s*|\\s*//[^/]*//\\s*|\\s{2,}");

	/** findet Leerzeichen und Kommentare am Ende einer Zeile */
	protected static final Pattern trim_end = Pattern
			.compile("(\\s+|\\s*//[^/]*)$");

	/** findet einen Anfang eines Unterblock */
	protected static final Pattern brackets_open = Pattern
			.compile("^(\\w+)\\s(.+)\\{$");

	/** findet das Ende eines Unterblock */
	protected static final Pattern brackets_close = Pattern.compile("^}$");

	/** findet einen Anfang eines Modells */
	protected static final Pattern model_start = Pattern.compile("^"
			+ SIMULATION_MODEL + ".*");

	/** findet einen Anfang eines Einheit */
	protected static final Pattern unit_start = Pattern.compile("^"
			+ SIMULATION_UNIT_NATURE_UNIT + ".*");

	/** findet einen Anfang eines Funktion */
	protected static final Pattern func_start = Pattern.compile("^("
			+ SIMULATION_UNIT_NATURE_AUX + "|" + SIMULATION_UNIT_NATURE_LEVEL
			+ "|" + SIMULATION_UNIT_NATURE_CONST + ").*");

	private static Logger logger = Logger.getLogger("simwave.converter.parser");
	private Hashtable<String, Hashtable<String, ParsedUnit>> parsed = null;
	private Hashtable<String, List<String>> sorted = null;
	private Hashtable<String, ParsedUnit> model = null;
	private Hashtable<String, ParsedUnit> units = new Hashtable<String, ParsedUnit>();;

	private String filename = null;
	private String name = null;
	private StringBuffer info = new StringBuffer();

	public Parser() {
	}

	public Hashtable<String, Hashtable<String, ParsedUnit>> getHashtableHashtableParsedUnit() {
		return parsed;
	}

	public String getName() {
		return name;
	}

	public StringBuffer getInfo() {
		return info;
	}

	public String getFilename() {
		return filename;
	}

	public Hashtable<String, ParsedUnit> getParsedUnits() {
		return model;
	}

	public Hashtable<String, List<String>> getSortedUnits() {
		return sorted;
	}
        public void startParse(String path) throws ParseException {
            
		filename = path;
		BufferedReader read = null;
		int lineCount = 0;
		try {
			File f = new File(path);                     
			read = new BufferedReader(new FileReader(path));
			parsed = new Hashtable<String, Hashtable<String, ParsedUnit>>();
			ParsedUnit unit = null;
			String name;
			String line, buffer = "";
			int level = 0;

			while ((line = read.readLine()) != null) {
				lineCount++;
				if (trim_ignore.matcher(line).matches())
					continue;

				line = trim_begin.matcher(line).replaceFirst("");
				line = trim_inner.matcher(line).replaceAll(" ");
				line = trim_end.matcher(line).replaceFirst("");

				// PowerSim Format vereinheitlichen
				line = line.replace("autodef", "def");
				line = line.replace("autotype", "type");
				line = line.replace("autounit", "unit");
				line = line.replace("autodim", "dim");

				if (level < 2 && brackets_open.matcher(line).matches()) {
					name = (line.lastIndexOf(' ') > line.indexOf(' ')) ? line
							.substring(line.indexOf(' ') + 1,
									line.lastIndexOf(' ')) : "";
					// Model
					// model=new Hashtable<String,ParsedUnit>();
					// parsed.put(name,model);
					// this.name=name;
					// unit=null;
					// System.out.println("print model_start "+model_start);
					// System.out.println("print func_start "+func_start);
					if (model_start.matcher(line).matches()) {
						//
						model = new Hashtable<String, ParsedUnit>();
						parsed.put(name, model);
						this.name = name;
                                                 System.out.println("Model Name:"+name);
						unit = null;
					}
					// Funktion
					else if (func_start.matcher(line).matches()) {
						// System.out.println("print name "+name);
						unit = new ParsedFormula();
						unit.setCodeline(lineCount);
						// unit.setContainer(this);
						unit.add(line.substring(0, line.length() - 2));
						// System.out.println(line.substring(0,line.length()-2));
						model.put(name, unit);
						// System.out.println("print function");
					}

					// Unit
					else if (unit_start.matcher(line).matches()) {
						unit = new ParsedUnit();
						unit.setCodeline(lineCount);
						// unit.setContainer(this);
						unit.add(line.substring(0, line.length() - 2));
						units.put(name, unit);
						// System.out.println("print unit");
					}
					level++;
				} else if (level <= 2 && brackets_close.matcher(line).matches()) {
					level--;
					// if(level==1)
					// parseUnit(unit);
				} else if (level >= 2 && !line.equals("")) {
					for (int i = 0; i < line.length(); i++)
						if (line.charAt(i) == '{' || line.charAt(i) == '(')
							level++;
						else if (line.charAt(i) == '}' || line.charAt(i) == ')')
							level--;
					if (level > 2)
						buffer = buffer + line;
					else if (level == 2) {
						if (buffer.length() > 0) {
							unit.add(buffer + line);
							buffer = "";
						} else {
							unit.add(line);
						}
					}
				}
				
				if (level < 0)
					throw new ParseException("Fehler in der Klammerstruktur");
			}
			if (level != 0)
				throw new ParseException("Fehler in der Klammerstruktur");
			parsed.put("units", units);
			read.close();

			lineCount = -1;

			

			for (java.util.Enumeration<String> names = units.keys(); names
					.hasMoreElements();) {
				unit = units.get(names.nextElement());
				unit.parse();

			}

			java.util.List<String> models = java.util.Collections.list(parsed
					.keys());
			models.remove("units");

			for (int i = 0; i < models.size(); i++) {
				model = parsed.get(models.get(i));
				
				parseFormulas();
				evaluateFormulas();
                               
                                
                                

			}			
        }
                catch (java.io.FileNotFoundException e) {
			String error = "Parser: Datei \"" + path
					+ "\" wurde nicht gefunden!";
			logger.severe(error);
			throw new ParseException(error);
		} catch (IOException e) {
			String error = "Parser: Fehler beim Lesen von Datei \"" + path
					+ "\" (Zeile " + lineCount + ")!";
			logger.severe(error);
			throw new ParseException(error);
		} catch (ParseException e) {
			String error = "Parser: Fehler beim Parsen von \"" + path + "\"";
			if (lineCount > -1)
				error += "(Zeile " + lineCount + ")";
			error += ": " + e.getLocalizedMessage();
			e.printStackTrace();
			logger.severe(error);
			try {
				if (read != null)
					read.close();
			} catch (Exception ioe) {
			}
			throw new ParseException(error);
		}
        }
        

	public void parse(String path) throws ParseException {
		long timestamp = System.currentTimeMillis();
		filename = path;
		BufferedReader read = null;
		int lineCount = 0;
		try {
			File f = new File(path);
                       

			read = new BufferedReader(new FileReader(path));
			parsed = new Hashtable<String, Hashtable<String, ParsedUnit>>();
			ParsedUnit unit = null;
			String name;

			String line, buffer = "";
			int level = 0;

			logger.info("Parser: Einlesen \"" + path + "\"");

			while ((line = read.readLine()) != null) {
				lineCount++;
				if (trim_ignore.matcher(line).matches())
					continue;

				line = trim_begin.matcher(line).replaceFirst("");
				line = trim_inner.matcher(line).replaceAll(" ");
				line = trim_end.matcher(line).replaceFirst("");

				// PowerSim Format vereinheitlichen
				line = line.replace("autodef", "def");
				line = line.replace("autotype", "type");
				line = line.replace("autounit", "unit");
				line = line.replace("autodim", "dim");

				if (level < 2 && brackets_open.matcher(line).matches()) {
					name = (line.lastIndexOf(' ') > line.indexOf(' ')) ? line
							.substring(line.indexOf(' ') + 1,
									line.lastIndexOf(' ')) : "";
					// Model
					// model=new Hashtable<String,ParsedUnit>();
					// parsed.put(name,model);
					// this.name=name;
					// unit=null;
					// System.out.println("print model_start "+model_start);
					// System.out.println("print func_start "+func_start);
					if (model_start.matcher(line).matches()) {
						//
						model = new Hashtable<String, ParsedUnit>();
						parsed.put(name, model);
						this.name = name;
						unit = null;
					}
					// Funktion
					else if (func_start.matcher(line).matches()) {
						// System.out.println("print name "+name);
						unit = new ParsedFormula();
						unit.setCodeline(lineCount);
						// unit.setContainer(this);
						unit.add(line.substring(0, line.length() - 2));
						// System.out.println(line.substring(0,line.length()-2));
						model.put(name, unit);
						// System.out.println("print function");
					}

					// Unit
					else if (unit_start.matcher(line).matches()) {
						unit = new ParsedUnit();
						unit.setCodeline(lineCount);
						// unit.setContainer(this);
						unit.add(line.substring(0, line.length() - 2));
						units.put(name, unit);
						// System.out.println("print unit");
					}
					level++;
				} else if (level <= 2 && brackets_close.matcher(line).matches()) {
					level--;
					// if(level==1)
					// parseUnit(unit);
				} else if (level >= 2 && !line.equals("")) {
					for (int i = 0; i < line.length(); i++)
						if (line.charAt(i) == '{' || line.charAt(i) == '(')
							level++;
						else if (line.charAt(i) == '}' || line.charAt(i) == ')')
							level--;
					if (level > 2)
						buffer = buffer + line;
					else if (level == 2) {
						if (buffer.length() > 0) {
							unit.add(buffer + line);
							buffer = "";
						} else {
							unit.add(line);
						}
					}
				}
				// if(!line.equals("")){
				// String lineNum=""+lineCount;
				// for(int i=lineNum.length();i<4;i++)lineNum=lineNum+" ";
				// logger.info("Parser: Zeile "+lineNum+" Level "+level+" "+line);
				// }
				if (level < 0)
					throw new ParseException("Fehler in der Klammerstruktur");
			}
			if (level != 0)
				throw new ParseException("Fehler in der Klammerstruktur");
			parsed.put("units", units);
			read.close();

			lineCount = -1;

			logger.info("Parser: Analysiere Einheiten");

			for (java.util.Enumeration<String> names = units.keys(); names
					.hasMoreElements();) {
				unit = units.get(names.nextElement());
				unit.parse();

			}

			java.util.List<String> models = java.util.Collections.list(parsed
					.keys());
			models.remove("units");

			for (int i = 0; i < models.size(); i++) {
				model = parsed.get(models.get(i));
				logger.info("Parser: Analysiere Modell \"" + models.get(i)
						+ "\"");
				parseFormulas();
				evaluateFormulas();

			}

			int countmodels = parsed.size() - 1, countunits = parsed.get(
					"units").size(), countfunctions = 0 - countunits;
			timestamp = System.currentTimeMillis() - timestamp;
			for (java.util.Enumeration<String> e = parsed.keys(); e
					.hasMoreElements(); countfunctions += parsed.get(
					e.nextElement()).size())
				;

			logger.info("Parser: \"" + path + "\" geparst in " + timestamp
					+ " ms: " + countmodels + " Model(e), " + countunits
					+ " Einheiten und " + countfunctions
					+ " Funktionen gefunden");
			return;
		} catch (java.io.FileNotFoundException e) {
			String error = "Parser: Datei \"" + path
					+ "\" wurde nicht gefunden!";
			logger.severe(error);
			throw new ParseException(error);
		} catch (IOException e) {
			String error = "Parser: Fehler beim Lesen von Datei \"" + path
					+ "\" (Zeile " + lineCount + ")!";
			logger.severe(error);
			throw new ParseException(error);
		} catch (ParseException e) {
			String error = "Parser: Fehler beim Parsen von \"" + path + "\"";
			if (lineCount > -1)
				error += "(Zeile " + lineCount + ")";
			error += ": " + e.getLocalizedMessage();
			e.printStackTrace();
			logger.severe(error);
			try {
				if (read != null)
					read.close();
			} catch (Exception ioe) {
			}
			throw new ParseException(error);
		}
	}

	private void parseFormulas() throws ParseException {
		logger.info("Parser: ... Analyse der Formeln");
		ParsedUnit unit;
		for (java.util.Enumeration<String> names = model.keys(); names
				.hasMoreElements();) {
			unit = model.get(names.nextElement());
			unit.parse();
		}
	}

	private void evaluateFormulas() throws ParseException {
		logger.info("Parser: ... Evaluierung der Formeln");

		ParsedFormula unit;

		for (java.util.Enumeration<String> names = model.keys(); names
				.hasMoreElements();) {
			unit = (ParsedFormula) model.get(names.nextElement());
			unit.parseFormula();
			
		}
		logger.info("Parser: ... Aufl�sen der Variablenverbindungen");
		for (java.util.Enumeration<String> names = model.keys(); names
				.hasMoreElements();) {                     
			unit = (ParsedFormula) model.get(names.nextElement());
			unit.evaluate(units, model);
                        output+=unit.get(Parser.SIMULATION_UNIT_NAME)+"\r\n";
                        if(unit.get(Parser.SIMULATION_UNIT_DEF)!=null)
                        output+=unit.get(Parser.SIMULATION_UNIT_DEF)+"\r\n";
                        else if(unit.get(Parser.SIMULATION_UNIT_INIT)!=null)
                        output+=unit.get(Parser.SIMULATION_UNIT_INIT)+"\r\n";
                        output+="\r\n";
                      
                       
                        
		}

	}
        
        public void modifyResult(String path,String content){
                   
            String s= new String();
            try{
                
            FileWriter fw = new FileWriter(path,false);  
s += content;  
fw.write(s,0,s.length());  
fw.flush(); 
fw.close();
            }
            catch(IOException e){
                e.printStackTrace();
                return;
        }
        }
      
      
        public void writeResult(String path,String content) {
            String name=path+"/result.txt";
            String s= new String();
            try{
                
            FileWriter fw = new FileWriter(name,false);  
s += content;  
fw.write(s,0,s.length());  
fw.flush(); 
fw.close();
            }
            catch(IOException e){
                e.printStackTrace();
                return;
            }
                
        }

	public void sortFormulas() {
		if (model.size() == 0)
			return;
		List<String> variables = Collections.list(model.keys());
		Collections.sort(variables);

		sorted.put("variables", variables);
		sorted.put("constants", new ArrayList<String>());
		sorted.put("init", new ArrayList<String>());
		sorted.put("auxilaries", new ArrayList<String>());
		sorted.put("levels", new ArrayList<String>());

		for (int i = 0; i < variables.size(); i++) {
			String name = variables.get(i);
			String nature = model.get(name).get(Parser.SIMULATION_UNIT_NATURE);
			if (nature.equals(Parser.SIMULATION_UNIT_NATURE_CONST))
				sorted.get("constants").add(name);
			else if (nature.equals(Parser.SIMULATION_UNIT_NATURE_AUX))
				sorted.get("auxilaries").add(name);
			else if (nature.equals(Parser.SIMULATION_UNIT_NATURE_LEVEL)) {
				sorted.get("init").add(name);
				sorted.get("levels").add(name);
			}
		}
		sorted.put("init",
				sortFormulas(Parser.SIMULATION_UNIT_INIT, sorted.get("init")));
		sorted.put(
				"auxilaries",
				sortFormulas(Parser.SIMULATION_UNIT_DEF,
						sorted.get("auxilaries")));

		// Filter (nur Levels und ausgew�hlte Auxilaries)
		ArrayList<String> filtered = new ArrayList<String>();
		ArrayList<String> keyList = new ArrayList<String>();

		for (int i = 0; i < variables.size(); i++) {
			String name = variables.get(i);
			ParsedUnit unit = model.get(name);
			if (unit.get(Parser.SIMULATION_UNIT_NATURE) == Parser.SIMULATION_UNIT_NATURE_LEVEL
					|| "public".equals(unit.get(Parser.SIMULATION_UNIT_NOTE)))
				if (unit.get(Parser.SIMULATION_UNIT_DIM) != null) {
					int max = Integer.parseInt(unit
							.get(Parser.SIMULATION_UNIT_DIM));
					for (int j = 1; j <= max; j++) {
						filtered.add(name + "(" + j + ")");
					}
				} else
					filtered.add(name);
			if (unit.get(Parser.SIMULATION_UNIT_DIM) != null) {
				int max = Integer
						.parseInt(unit.get(Parser.SIMULATION_UNIT_DIM));
				for (int j = 1; j <= max; j++) {
					keyList.add(name + "(" + j + ")");
				}
			} else
				keyList.add(name);

		}

		sorted.put("variables", keyList);

		Collections.sort(filtered);
		sorted.put("filtered", filtered);
	}

	public List<String> sortFormulas(String container, List<String> variables) {
		int minOrder = 0;
		int[] orderList = new int[variables.size()];

		for (int i = 0; i < orderList.length; i++)
			orderList[i] = 1;

		ArrayList<String> sorted = new ArrayList<String>(orderList.length);

		for (int i = 0; i < variables.size(); i++) {
			if (orderList[i] == 1)
				orderList[i] = getOrder(container, variables, variables.get(i),
						orderList, i);
			minOrder = Math.min(orderList[i], minOrder);
			
		}

		for (int i = minOrder; i <= 0; i++) {
			for (int j = 0; j < variables.size(); j++) {
				if (orderList[j] == i) {
					sorted.add(variables.get(j));
				}
			}
		}
		return sorted;
	}

	private int getOrder(String container, List<String> variables, String name,
			int[] orderList, int i) {
		if (orderList[i] < 1)
			return orderList[i];
		int order = 0;
		ParsedFormula formula;
		for (int j = 0; j < orderList.length; j++) {
			formula = (ParsedFormula) model.get(variables.get(j));
			if (i != j && formula.getVariables(container).contains(name)) {
				order = Math.min(
						getOrder(container, variables, variables.get(j),
								orderList, j) - 1, order);
			}
		}
		orderList[i] = order;
		return order;
	}

	public static void printParse(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		for (java.util.Enumeration<String> e = output.keys(); e
				.hasMoreElements();) {
			String name = e.nextElement();
			System.out.println("[" + name + "] {");
			Hashtable<String, ParsedUnit> model = output.get(name);
			int count = 0;
			java.util.List<String> list = java.util.Collections.list(model
					.keys());
			java.util.Collections.sort(list);
			java.util.Enumeration<String> x = java.util.Collections
					.enumeration(list);
			for (; x.hasMoreElements();) {
				String key = x.nextElement();
				ParsedUnit fun = model.get(key);
				System.out.println("\t" + count++ + " := " + fun.toString());

			}
			System.out.println("}");
		}
	}

	public static void printParseXML(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		System.out.println("<?xml version=\"1.0\"?>");
		System.out.println("<models>");
		for (java.util.Enumeration<String> e = output.keys(); e
				.hasMoreElements();) {
			String name = e.nextElement();
			if (name.equals("units"))
				System.out.println("<units>");
			else
				System.out.println("<model name=\"" + name + "\">");
			Hashtable<String, ParsedUnit> model = output.get(name);

			java.util.List<String> list = java.util.Collections.list(model
					.keys());
			java.util.Collections.sort(list);
			java.util.Enumeration<String> x = java.util.Collections
					.enumeration(list);
			for (; x.hasMoreElements();) {
				String key = x.nextElement();
				ParsedUnit fun = model.get(key);
				List<String> funlist = fun.getKeys();
				funlist.remove(Parser.SIMULATION_UNIT_NAME);
				funlist.remove(Parser.SIMULATION_UNIT_NATURE);
				System.out.print("<" + fun.get(Parser.SIMULATION_UNIT_NATURE)
						+ " name=\"" + fun.get(Parser.SIMULATION_UNIT_NAME)
						+ "\">");
				for (int i = 0; i < funlist.size(); i++)
					System.out.print("<"
							+ funlist.get(i)
							+ ">"
							+ fun.get(funlist.get(i))
									.replaceAll("<<", "UNIT[[")
									.replaceAll(">>", "]]") + "</"
							+ funlist.get(i) + ">");
				System.out.print("</" + fun.get(Parser.SIMULATION_UNIT_NATURE)
						+ ">\n");
			}
			if (name.equals("units"))
				System.out.println("</units>");
			else
				System.out.println("</model>");
		}
		System.out.println("</models>");
	}

	public static void printDefinition(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		for (java.util.Enumeration<String> e = output.keys(); e
				.hasMoreElements();) {
			String name = e.nextElement();
			Hashtable<String, ParsedUnit> model = output.get(name);
			java.util.List<String> list = java.util.Collections.list(model
					.keys());
			java.util.Collections.sort(list);
			java.util.Enumeration<String> x = java.util.Collections
					.enumeration(list);
			for (; x.hasMoreElements();) {
				String key = x.nextElement();
				ParsedUnit fun = model.get(key);
				if (fun.get(Parser.SIMULATION_UNIT_INIT) != null)
					System.out.println("init " + key + " := "
							+ fun.get(Parser.SIMULATION_UNIT_INIT));
				if (fun.get(Parser.SIMULATION_UNIT_DEF) != null)
					System.out.println("def  " + key + " := "
							+ fun.get(Parser.SIMULATION_UNIT_DEF));
			}
		}
	}

	public static String getGo4CDefinition(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		StringBuilder buff = new StringBuilder();
		java.util.List<String> models = java.util.Collections.list(output
				.keys());
		models.remove("units");
		char seperator = ';';

		for (int i = 0; i < models.size(); i++) {
			Hashtable<String, ParsedUnit> model = output.get(models.get(i));
			java.util.List<String> list = java.util.Collections.list(model
					.keys());
			java.util.Collections.sort(list);
			java.util.Enumeration<String> x = java.util.Collections
					.enumeration(list);
			buff.append("varName").append(seperator).append("varType")
					.append(seperator).append("varUnit\r\n");
			for (; x.hasMoreElements();) {
				String key = x.nextElement();
				ParsedUnit fun = model.get(key);
				if (Parser.SIMULATION_UNIT_NATURE_UNIT.equals(fun
						.get(Parser.SIMULATION_UNIT_NATURE)))
					continue; // skip units

				String nature = fun
						.get(Parser.SIMULATION_UNIT_NATURE)
						.replace(Parser.SIMULATION_UNIT_NATURE_AUX, "Auxiliary")
						.replace(Parser.SIMULATION_UNIT_NATURE_LEVEL, "Level")
						.replace(Parser.SIMULATION_UNIT_NATURE_CONST,
								"Constant");
				String dim = fun.get(Parser.SIMULATION_UNIT_DIM);
				String unit = fun.get(Parser.SIMULATION_UNIT_UNIT);

				if (unit == null)
					unit = "";
				if (dim == null) {
					buff.append(key).append(seperator).append(nature)
							.append(seperator).append(unit).append("\r\n");
				} else {
					for (int d = 1; d <= Integer.parseInt(dim); d++)
						buff.append(key).append('(').append(d).append(')')
								.append(seperator).append(nature)
								.append(seperator).append(unit).append("\r\n");
				}
			}
		}
		// remove tail linefeeds
		buff.deleteCharAt(buff.length() - 1);
		buff.deleteCharAt(buff.length() - 1);
		return buff.toString();
	}

	public static void printGo4CDefinition(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		System.out.println(getGo4CDefinition(output));
	}

	public static String getVariableDependencyGraph(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		StringBuilder buff = new StringBuilder();
		java.util.List<String> models = java.util.Collections.list(output
				.keys());
		models.remove("units");
		String inter = "--";
		char seperator = ';';
		String attr = "shape=\"circle\" len=\"10\" fontsize=\"1.0\" penwidth=\"0.05\"";

		buff.append("graph abstract {\ncenter=true;\noutputorder=nodesfirst;\n");

		for (int i = 0; i < models.size(); i++) {
			Hashtable<String, ParsedUnit> model = output.get(models.get(i));
			java.util.List<String> list = java.util.Collections.list(model
					.keys());
			java.util.Collections.sort(list);
			java.util.Enumeration<String> x = java.util.Collections
					.enumeration(list);
			for (; x.hasMoreElements();) {
				String key = x.nextElement();
				ParsedUnit fun = model.get(key);
				if (Parser.SIMULATION_UNIT_NATURE_UNIT.equals(fun
						.get(Parser.SIMULATION_UNIT_NATURE)))
					continue; // skip units
	
				String unit = fun.get(Parser.SIMULATION_UNIT_UNIT);

				if (unit == null)
					unit = "";
				List<String> variables = ((ParsedFormula) fun)
						.getVariables(Parser.SIMULATION_UNIT_DEF);
				for (String var_name : variables) {
					ParsedUnit var = model.get(var_name);
					if (var == null
							|| var_name.equals(key)
							|| Parser.SIMULATION_UNIT_NATURE_UNIT.equals(var
									.get(Parser.SIMULATION_UNIT_NATURE)))
						continue; // skip units

					buff.append(var_name).append(inter).append(key)
							.append(" [").append(attr).append("]")
							.append(seperator).append("\r\n");
				}
			}
		}
		buff.append('}');
		return buff.toString();
	}

	public static void printVariableDependencyGraph(
			Hashtable<String, Hashtable<String, ParsedUnit>> output) {
		System.out.println(getVariableDependencyGraph(output));
	}
        public void parseResult(String inputPath, String outputPath) {
		try{	
                startParse(inputPath);
                writeResult(outputPath, output);}
                catch(ParseException e){
                }
	}

	/**
	 * Test
	 * 
	 * @throws Exception
	 */
	public static void main(String args[]) throws Exception {

		logger.setLevel(Level.ALL);
		Logger root = Logger.getLogger("");
		root.setLevel(Level.ALL);
		Handler[] handlers = root.getHandlers();
		for (int i = 0; i < handlers.length; i++)
			root.removeHandler(handlers[i]);


		String filename = "SimModel_v7_70.txt";
		Parser parser = new Parser();
                parser.startParse(filename);

	}
}